import threading
from datetime import datetime as datetime_
import multiprocessing


def task(data, idx_addend, variable_value, queue):
    """多进程函数"""
    import os
    import django

    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'noflip_web.settings')
    django.setup()
    # 动态导入模型和模块
    from object.single.parts import SingleBacktest
    # 创建回测实例
    backtest_ins = SingleBacktest(data, idx_addend, variable_value, queue)
    # 生成因子line
    backtest_ins.set_factor()
    # 设置战法实例
    backtest_ins.set_tactic_ins()
    # 执行遍历
    backtest_ins.traverse()
    # stage2 将整合和生成仓位、净值数据的内容放在这里
    from object.single.parts import SingleIntegrateProcess
    single_integrate_process_ins = SingleIntegrateProcess()
    single_integrate_process_ins.set_bt_ins(backtest_ins)
    single_integrate_process_ins.set_com_order_ls(backtest_ins.com_order_ls)
    single_integrate_process_ins.gen_datetime_ls()
    single_integrate_process_ins.gen_close_ls()
    single_integrate_process_ins.gen_pos_ls()
    # single_integrate_process_ins.gen_value_ls()
    bt_data = [single_integrate_process_ins.com_datetime_ls, single_integrate_process_ins.com_close_ls,
               single_integrate_process_ins.com_pos_ls]
    return_bt_data = ["process_bt_data", backtest_ins.idx_addend, bt_data]
    queue.put(return_bt_data)


def receive(results, process_number, variable_value, queue):
    # 等待所有进程完成并从队列中收集结果
    complete_process_num = 0
    while True:
        result = queue.get()
        # 根据进程结束时返回的数据[mess_type, idx_addend, com_order_ls]
        if result[0] == "process_bt_data":
            complete_process_num += 1
            results.append(result)
            if complete_process_num >= process_number:
                break
        elif result[0] == "process":
            # 接收到的是回测过程数据
            # 将其更新至前端
            # 过程数据格式为[mess_type, idx_addend, now_index, max_index]
            # 修改variable相关的process数据
            variable_value["lab_var_part2_5"]["progress"]["进程" + str(result[1])] = round(result[2] / result[3], 2)
        elif result[0] == "end":
            pass
        else:
            raise ValueError("不兼容的数据类型，逻辑错误。")


def start_process_v2_alone(variable_value, data_ins, queue, process_number):
    """启动多进程"""
    if multiprocessing.get_start_method() != 'spawn':
        multiprocessing.set_start_method('spawn')

    results = []

    # 启动监听线程
    listener_thread = threading.Thread(target=receive, args=(results, process_number, variable_value, queue,))
    listener_thread.start()

    # 创建进程池，池中进程的数量等于任务数量
    pool = multiprocessing.Pool(processes=process_number)  # 使用可用CPU核心数的进程池

    processes = []
    idx_addend = 0
    for data_o in data_ins.group_cont:
        p = multiprocessing.Process(target=task, args=(data_o, idx_addend, variable_value, queue))
        processes.append(p)
        idx_addend += len(data_o)
    try:
        # 启动所有进程
        for p_o in processes:
            p_o.start()

        # 等待所有进程结束
        for p_o in processes:
            p_o.join()
    except Exception as e:
        print(e)

    sorted_results = sorted(results, key=lambda x: x[1])
    # 进一步的结果处理逻辑
    return sorted_results
